using System;
using Microsoft.SPOT;
using System.Threading;

namespace nRF24L10P.Roles
{
    public class SimpleSendRole : IRole 
    {
        private nRF24L10P device;
        private object syncRoot = new object();
        public byte[] Address { get; set; }
        //private int length;
        DataReadPipe reader;
        DataWritePipe writer;
        public bool IsRunning { get; private set; }
        private ManualResetEvent sentEvent;
        private bool maxRT = false;
        public SimpleSendRole()
        {
            sentEvent = new ManualResetEvent(false);
        }

        public void Start()
        {
            if (IsRunning)
            {
                return;
            }
            device.Status = DeviceStatusEnum.PowerDown; //shut down device for config

            reader = device.RXPipes[0]; //use the first receive channel, this is for auto ACK
            writer = device.TXPipe;
            
            

            //enable dynamic package length by default
            device.Config.DynamicPayloadLengthEnabled = true;

            //enable autoACK
            reader.AutoACKEnabled = true;
            reader.DynamicPayloadLengthEnabled = true;
            reader.Address = this.Address;
            reader.Enabled = true;

            writer.Address = this.Address;

            device.FlushRX();
            device.FlushTX();

            device.OnInterrupt += device_OnInterrupt;

            device.Status = DeviceStatusEnum.StandBy;
            device.Status = DeviceStatusEnum.TXMode; // put the device into TX mode
            IsRunning = true;
        }

        private void device_OnInterrupt(Register.Register_STATUS status)
        {
            if (status.TX_DS||status.MAX_RT)// data sent
            {
                device.FlushTX(); // clear TX FIFO 
                maxRT = status.MAX_RT;
                device.Status = DeviceStatusEnum.StandBy;

                status.Save(); // clear flags

                device.Status = DeviceStatusEnum.TXMode;
                
                sentEvent.Set();
                return;
            }
            
            

        }

        public void Stop()
        {
            if (!IsRunning)
            {
                return;
            }
            device.OnInterrupt -= device_OnInterrupt;
            device.Status = DeviceStatusEnum.StandBy;
            device.Status = DeviceStatusEnum.PowerDown;
            IsRunning = false;
        }

        public void AttachDevice(nRF24L10P device)
        {
            this.device = device;
        }

        public void DetachDevice()
        {
            this.device = null;
        }

        /// <summary>
        /// put buffer to chip's TX FIFO, buffer should not longer than 32 byes 
        /// </summary>
        /// <param name="buffer"></param>
        public void SendAsync(byte[] buffer)
        {
            if (buffer.Length>32)
            {
                throw new ArgumentOutOfRangeException("buffer", "buffer should less than 32 bytes");
            }
            writer.Write(buffer);
        }


        public bool Send(byte[] buffer,int timeOut=1000)
        {
            if (buffer.Length > 32)
            {
                throw new ArgumentOutOfRangeException("buffer", "buffer should less than 32 bytes");
            }
            sentEvent.Reset();
            SendAsync(buffer);
            return  sentEvent.WaitOne(timeOut, false) && !maxRT;
        }
    }
}
